Skip to content

Conversation

@tlgimenes
Copy link
Contributor

@tlgimenes tlgimenes commented Jan 6, 2026

Summary by cubic

Fixed real-time LLM streaming for OpenRouter by using the correct provider API and returning proper error responses. This prevents broken streams and surfaces accurate status, headers, and body on failures.

  • Bug Fixes

    • Switched from openrouter.languageModel(modelId) to openrouter(modelId) for streaming.
    • Wrapped doStream in try/catch and mapped APICallError to Response with status, headers, and body.
    • Return 500 with a simple message for non-API errors.
  • Dependencies

    • Updated @openrouter/ai-sdk-provider to ^1.5.4.
    • Updated @ai-sdk/provider to ^3.0.2 and @ai-sdk/provider-utils to ^4.0.4.
    • Refreshed lockfile to align transitive versions.

Written for commit efc81fb. Summary will update on new commits.

@tlgimenes tlgimenes merged commit 9fab04a into main Jan 6, 2026
5 of 9 checks passed
@github-actions
Copy link

github-actions bot commented Jan 6, 2026

🚀 Preview Deployments Ready!

Your changes have been deployed to preview environments:

📦 openrouter

🔗 View Preview

These previews will be automatically updated with new commits to this PR.


Deployed from commit: e5a9d4e

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 3 files

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="openrouter/server/tools/llm-binding.ts">

<violation number="1" location="openrouter/server/tools/llm-binding.ts:471">
P2: Use `APICallError.isInstance(error)` instead of a custom symbol-based type guard. The AI SDK provides this static method specifically for type checking, and relying on internal symbols (`Symbol.for(&#39;vercel.ai.error&#39;)`) is fragile and could break with SDK updates.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment on lines +471 to +475
const isAPICallError = (error: unknown): error is APICallError =>
typeof error === "object" &&
error !== null &&
Symbol.for("vercel.ai.error") in error &&
Symbol.for("vercel.ai.error.AI_APICallError") in error;
Copy link

@cubic-dev-ai cubic-dev-ai bot Jan 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Use APICallError.isInstance(error) instead of a custom symbol-based type guard. The AI SDK provides this static method specifically for type checking, and relying on internal symbols (Symbol.for('vercel.ai.error')) is fragile and could break with SDK updates.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At openrouter/server/tools/llm-binding.ts, line 471:

<comment>Use `APICallError.isInstance(error)` instead of a custom symbol-based type guard. The AI SDK provides this static method specifically for type checking, and relying on internal symbols (`Symbol.for(&#39;vercel.ai.error&#39;)`) is fragile and could break with SDK updates.</comment>

<file context>
@@ -467,6 +468,12 @@ const getUsageFromStream = (
   ];
 };
 
+const isAPICallError = (error: unknown): error is APICallError =&gt;
+  typeof error === &quot;object&quot; &amp;&amp;
+  error !== null &amp;&amp;
</file context>
Suggested change
const isAPICallError = (error: unknown): error is APICallError =>
typeof error === "object" &&
error !== null &&
Symbol.for("vercel.ai.error") in error &&
Symbol.for("vercel.ai.error.AI_APICallError") in error;
const isAPICallError = (error: unknown): error is APICallError =>
APICallError.isInstance(error);
Fix with Cubic

tlgimenes added a commit that referenced this pull request Jan 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants